<?php
/***************************************************************
*  Copyright notice
*  (c) 2009, jianyuzhu@gmail.com
*  All rights reserved
*  This script is part of the PPEMI project.
***************************************************************/

class LibCCValidation {
	var $cc_type;
	var $cc_number;
	var $cc_expiry_month;
	var $cc_expiry_year;
	
	//methods
	function getCCType($number) {
		$number = ereg_replace('[^0-9]', '', $number);
		
		if( ereg('^4[0-9]{12}([0-9]{3})?$', $number)) {
			$this->cc_type = 'Visa';
		} elseif( ereg('^5[1-5][0-9]{14}$', $number)) {
			$this->cc_type = 'Master Card';
		} elseif( ereg('^3[47][0-9]{13}$', $number)) {
			$this->cc_type = 'American Express';
		} elseif( ereg('^3(0[0-5]|[68][0-9])[0-9]{11}$', $number)) {
			$this->cc_type = 'Diners Club';
		} elseif( ereg('^6011[0-9]{12}$', $number)) {
			$this->cc_type = 'Discover';
		} elseif( ereg('^(3[0-9]{4}|2131|1800)[0-9]{11}$', $number)) {
			$this->cc_type = 'JCB';
		} elseif( ereg('^5610[0-9]{12}$', $number)) { 
			$this->cc_type = 'Australian BankCard';
		} else {
			return -1;
		}
	}
	
	function getCCTypes() {
		$types = array(
				'1' => 'Visa',
				'2' => 'Master Card',
				'3' => 'American Express',
				'4' => 'Diners Club',
				'5' => 'Discover',
				'6' => 'JCB',
				'7' => 'Australian BankCard',
					);
		
		return $types;
	}
	
	function validate($number, $expiry_m, $expiry_y) {
		$this->cc_number = ereg_replace('[^0-9]', '', $number);
		
		if( ereg('^4[0-9]{12}([0-9]{3})?$', $this->cc_number)) {
			$this->cc_type = 'Visa';
		} elseif( ereg('^5[1-5][0-9]{14}$', $this->cc_number)) {
			$this->cc_type = 'Master Card';
		} elseif( ereg('^3[47][0-9]{13}$', $this->cc_number)) {
			$this->cc_type = 'American Express';
		} elseif( ereg('^3(0[0-5]|[68][0-9])[0-9]{11}$', $this->cc_number)) {
			$this->cc_type = 'Diners Club';
		} elseif( ereg('^6011[0-9]{12}$', $this->cc_number)) {
			$this->cc_type = 'Discover';
		} elseif( ereg('^(3[0-9]{4}|2131|1800)[0-9]{11}$', $this->cc_number)) {
			$this->cc_type = 'JCB';
		} elseif( ereg('^5610[0-9]{12}$', $this->cc_number)) { 
			$this->cc_type = 'Australian BankCard';
		} else {
			return -1;
		}
		
		if( is_numeric($expiry_m) && ($expiry_m > 0) && ($expiry_m < 13)) {
			$this->cc_expiry_month = $expiry_m;
		} else {
			return -2;
		}
		
		$current_year = date('Y');
		$expiry_y = substr($current_year, 0, 2) . $expiry_y;
		if( is_numeric($expiry_y) && ($expiry_y >= $current_year) && ($expiry_y <= ($current_year + 10))) {
			$this->cc_expiry_year = $expiry_y;
			
		} else {
			return -3;
		}
			
		if( $expiry_y == $current_year) {
			if( $expiry_m < date('n')) {
				return -4;
			}
		}
		
		//
		$this->cc_expires_month = $this->cc_expiry_month;
		$this->cc_expires_year = substr($this->cc_expiry_year, -2);
		$this->cc_expires = $this->cc_expires_month . $this->cc_expires_year;
		
		return $this->is_valid();
	}
	
	function is_valid() {
		$cardNumber = strrev($this->cc_number);
		$numSum = 0;
		
		for ($i=0; $i<strlen($cardNumber); $i++) {
			$currentNum = substr($cardNumber, $i, 1);
			
			// Double every second digit
			if( $i % 2 == 1) {
				$currentNum *= 2;
			}
			
			// Add digits of 2-digit numbers together
			if( $currentNum > 9) {
				$firstNum = $currentNum % 10;
				$secondNum = ($currentNum - $firstNum) / 10;
				$currentNum = $firstNum + $secondNum;
			}
			
			$numSum += $currentNum;
		}
		
		// If the total has no remainder it's OK
		return ($numSum % 10 == 0);
	}
	
	//
	function check($number, $expiry_m, $expiry_y, $owner, $cpin) {
		global $LANGUAGE;
		func_lang_load_package('payment');
		
		$expiry_m = sprintf('%02d', $expiry_m);
		$expiry_y = substr($expiry_y, -2);
		
		$this->cc_error = false;
		$this->cc_msg = '';
		$result = $this->validate($number, $expiry_m, $expiry_y);
		$error = '';
		switch($result) {
			case -1:
				$error = sprintf($LANGUAGE['payment']['text_ccval_error_unknown_card'], substr($this->cc_number, 0, 4));
				break;
			case -2:
			case -3:
			case -4:
				$error = $LANGUAGE['payment']['text_ccval_error_invalid_date'];
				break;
			case false:
				$error = $LANGUAGE['payment']['text_ccval_error_invalid_number'];
				break;
		}
		if( ($result == false) || ($result < 1) ) {
			$this->cc_error = true;
			$this->cc_msg = $error;
		}
		
		//$this->cc_type
		//$this->cc_number
		//$this->cc_expiry_month
		//$this->cc_expiry_year
		$this->cc_expires_month = $this->cc_expiry_month;
		$this->cc_expires_year = substr($this->cc_expiry_year, -2);
		$this->cc_expires = $this->cc_expiry_month . substr($this->cc_expiry_year, -2);
		$this->cc_owner = $owner;
		$this->cc_cpin = $cpin;
	}
}
//
?>